package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"

	"github.com/xuri/excelize/v2"
)

// 定义工作簿结构体
type WorkBook struct {
	FileName string `json:"filename"`
	Sheet    []struct {
		Sheet2
	} `json:"sheet"`
}

// 定义工作表结构体
type Sheet2 struct {
	Name  string `json:"name"`
	Title string `json:"title"`
	Table Table  `json:"table"`
	Index int    `json:"index"`
	// Annotation map[string]map[string]string `json:"annotation"` //批注
	Annotation map[string]string `json:"annotation"` //批注

	// Formula []string            `json:"formula"`
	Args map[string][]string `json:"args"`
}
type Table struct {
	ColTable       []string `json:"coltable"`
	RowTable       []string `json:"rowtable"`
	SecondRowTable []string `json:"secondrowtable"`
	ColSize        int      `json:"colsize"`
	RowSize        int      `json:"rowsize"`
}

// 读取json配置文件
func GetJson(file string) WorkBook {
	jsonF, err := os.Open("config.json")
	if err != nil {
		fmt.Println("error opening file err:", err)
	}
	defer jsonF.Close()
	jsonData, err := ioutil.ReadAll(jsonF)
	if err != nil {
		fmt.Println("read json err:", err)
	}
	var s WorkBook
	json.Unmarshal(jsonData, &s)
	return s
}

// 索引转列名
func ColToName(i int) string {
	str, _ := excelize.ColumnNumberToName(i)
	return str
}

// 列名转索引
func ColNameToNum(i string) int {
	n, _ := excelize.ColumnNameToNumber(i)
	return n
}

func main() {
	s := GetJson("config.json")
	fmt.Printf("json response :%v\n", s.Sheet[1].Args)

	// 创建xlsx文件
	f := excelize.NewFile()
	// 设置工作表整体格式
	style1, err := f.NewStyle(&excelize.Style{
		Border: []excelize.Border{
			{Type: "left", Color: "000000", Style: 2},
			{Type: "top", Color: "000000", Style: 2},
			{Type: "bottom", Color: "000000", Style: 2},
			{Type: "right", Color: "000000", Style: 2},
		},
		Font:      &excelize.Font{Color: "000000", Bold: true, Size: 11, Family: "宋体"},
		Alignment: &excelize.Alignment{Vertical: "center", Horizontal: "center", WrapText: true},
	})
	if err != nil {
		fmt.Println("style1 err:", err)
	}
	// 设置标题格式
	style2, err := f.NewStyle(&excelize.Style{
		Font:      &excelize.Font{Color: "000000", Bold: true, Size: 20, Family: "宋体"},
		Alignment: &excelize.Alignment{Vertical: "center", Horizontal: "center", WrapText: true},
	})
	if err != nil {
		fmt.Println("style2 err:", err)
	}

	// 建立工作记录表
	index := f.NewSheet(s.Sheet[0].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[0].Name, index)
	// fmt.Println(s.Sheet[0].Annotation)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[0].Name, "A1", s.Sheet[0].Title)
	f.SetSheetRow(s.Sheet[0].Name, "A2", &s.Sheet[0].Table.RowTable)
	err = f.MergeCell(s.Sheet[0].Name, "A1", ColToName(len(s.Sheet[0].Table.RowTable))+"1")
	if err != nil {
		fmt.Println("MergeCell err:", err)
	}
	// 添加批注
	// fmt.Println(s.Sheet[0].Annotation)
	for k, v := range s.Sheet[0].Annotation {
		// fmt.Println("k:", k, "v:", v)
		err = f.AddComment(s.Sheet[0].Name, k, v)
		if err != nil {
			fmt.Println("AddComment err:", err)
		}
	}

	// 设置格式
	err = f.SetCellStyle(s.Sheet[0].Name, "A1", ColToName(len(s.Sheet[0].Table.RowTable))+"6", style1)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	err = f.SetCellStyle(s.Sheet[0].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	// 设置列宽
	var colWidth = []float64{4.64, 7.42, 6.58, 6.74, 5.49, 27.24, 28.49, 5.12, 4, 8.53, 13.4, 13.4, 7.36, 3.74, 6.9, 4.73, 8.4, 8.4, 7.4, 4.7}
	for i := 0; i < 20; i++ {
		err = f.SetColWidth(s.Sheet[0].Name, ColToName(1+i), ColToName(1+i), colWidth[i])
		// fmt.Printf("Width:%T\n", colWidth[i])
		if err != nil {
			fmt.Println("Set ColWidth err:", err)
		}
	}
	// 添加自动筛选
	err = f.AutoFilter(s.Sheet[0].Name, "A2", "P2", "")
	if err != nil {
		fmt.Println("Set AutoFilter err:", err)
	}
	// 添加冻结窗口
	f.SetPanes(s.Sheet[0].Name, `{
		"freeze":true,
		"split":false,
		"x_split":0,
		"y_split":2,
		"top_left_cell":"B3",
		"activate_pane":"topRight",
		"panes":[{
			"sqref":"",
			"active_cell":"",
			"pane":"topRight"
		}]
	}`)

	// 建立换件分类统计表
	index = f.NewSheet(s.Sheet[1].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[1].Name, index)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[1].Name, "A1", s.Sheet[1].Title)
	// 写入换件分类统计表coltable
	year := s.Sheet[1].Args["year"]
	month := s.Sheet[1].Table.SecondRowTable
	tail := s.Sheet[1].Args["tail"]
	// fmt.Println(tail, month)
	for i := 0; i < len(s.Sheet[1].Table.ColTable); i++ {
		f.SetCellValue(s.Sheet[1].Name, "A"+strconv.Itoa(3+i), s.Sheet[1].Table.ColTable[i])
	}
	// 写入换件分类统计表rowtable
	for j := 0; j < len(s.Sheet[1].Table.RowTable); j++ {
		f.SetCellValue(s.Sheet[1].Name, ColToName(2+j*13)+"2", s.Sheet[1].Table.RowTable[j])
		f.MergeCell(s.Sheet[1].Name, ColToName(2+j*13)+"2", ColToName(14+j*13)+"2")
		// 写入secondrowtable
		for k := 0; k < len(s.Sheet[1].Table.SecondRowTable); k++ {
			f.SetCellValue(s.Sheet[1].Name, ColToName(2+j*13+k)+"3", s.Sheet[1].Table.SecondRowTable[k])
		}
	}
	f.SetColWidth(s.Sheet[1].Name, "B", "CA", 3.6) //设置列宽
	// 写入公式

	for j := 0; j < len(s.Sheet[1].Table.RowTable); j++ {
		for k := 0; k < len(s.Sheet[1].Table.SecondRowTable)-1; k++ {
			for i := 0; i < len(s.Sheet[1].Table.ColTable)-1; i++ {
				formula := "=COUNTIFS(工作记录表!B:B,\"" + year[0] + "." + strings.Split(month[k], "月")[0] + ".*\",工作记录表!H:H,\"是\",工作记录表!I:I,A" + strconv.Itoa(4+i) + tail[j]
				// fmt.Println("second:", formula)
				err := f.SetCellFormula(s.Sheet[1].Name, ColToName(2+k+j*13)+strconv.Itoa(4+i), formula)

				if err != nil {
					fmt.Println("setCellFormula err:", err)
				}

			}
		}

	}

	for j := 0; j < len(s.Sheet[1].Table.RowTable); j++ {
		for k := 0; k < len(s.Sheet[1].Table.ColTable)-1; k++ {
			Sum := "=SUM(" + ColToName(2+13*j) + strconv.Itoa(4+k) + ":" + ColToName(13+13*j) + strconv.Itoa(4+k) + ")"
			// fmt.Println(Sum)
			err := f.SetCellFormula(s.Sheet[1].Name, ColToName(14+13*j)+strconv.Itoa(4+k), Sum)
			if err != nil {
				fmt.Println("SetCellFormula Sum err:", err)
			}

		}

	}

	rSize := len(s.Sheet[1].Table.SecondRowTable)*6 + 1
	cSize := len(s.Sheet[1].Table.ColTable) + 2
	// fmt.Println(ColToName(rSize), cSize)
	err = f.SetCellStyle(s.Sheet[1].Name, "A1", ColToName(rSize)+strconv.Itoa(cSize), style1)
	if err != nil {
		fmt.Println("Set style err:", err)
	}
	err = f.MergeCell(s.Sheet[1].Name, "A1", ColToName(rSize)+"1")
	if err != nil {
		fmt.Println("Merge err:", err)
	}
	err = f.SetCellStyle(s.Sheet[1].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	// 创建条件格式,值大于0的单元格标红
	format, err := f.NewConditionalStyle(`{
		"font":
		{
			"color": "#9A0511"
		},
		"fill":
		{
			"type": "pattern",
			"color": ["#FEC7CE"],
			"pattern": 1
		}
	}`)
	if err != nil {
		fmt.Println(err)
	}
	// 设置条件格式
	f.SetConditionalFormat(s.Sheet[1].Name, "B4:"+ColToName(rSize)+strconv.Itoa(cSize), fmt.Sprintf(`[
	{
		"type": "cell",
		"criteria": ">",
		"format": %d,
		"value": "0"
	}]`, format))
	fmt.Println("B4:" + ColToName(rSize) + strconv.Itoa(cSize))
	// 设置冻结窗口
	f.SetPanes(s.Sheet[1].Name, `{
		"freeze":true,
		"split":false,
		"x_split":1,
		"y_split":3,
		"top_left_cell":"B3",
		"activate_pane":"topRight",
		"panes":[{
			"sqref":"",
			"active_cell":"",
			"pane":"topRight"
		}]
	}`)

	var c1 []map[string]string
	c1 = make([]map[string]string, 0)

	for i := 3; i < cSize; i++ {
		c1 = append(c1, map[string]string{
			"name":       "换件分类统计表!$A$" + strconv.Itoa(i+1),
			"categories": "换件分类统计表!$B$3:$M$3",
			"values":     "换件分类统计表!$B$" + strconv.Itoa(i+1) + ":$M$" + strconv.Itoa(i+1),
		})
	}
	// fmt.Println(c1, len(c1))
	var c2 string
	var c3 []string
	for i := 0; i < len(c1); i++ {
		// fmt.Println(c1[i])
		c4, err := json.Marshal(c1[i])
		c3 = append(c3, string(c4))
		if err != nil {
			fmt.Println("json.Marshal err:", err)
		}
		if i <= len(c1)-2 {
			c2 = c2 + c3[i] + ",\n"
		} else {
			c2 = c2 + c3[i] + "\n"
		}

	}
	// fmt.Println(c2)

	str1 := `{
	        "type": "col",
	        "series": [`
	str2 := `
	],
	"format":
		{
			"x_scale": 3.0,                           
			"y_scale": 1.5,
			"x_offset": 55,
			"y_offset": 30,
			"print_obj": false,
			"lock_aspect_ratio": false,
			"locked": false
		},
		"legend":
		{
			"position": "left",
			"show_legend_key": false
		},
		"title":
		{
			"name": "换件分类统计表"
		},
		"plotarea":
		{
			"show_bubble_size": false,
			"show_cat_name": false,
			"show_leader_lines": false,
			"show_percent": false,
			"show_series_name": true,
			"show_val": true
		},
		"show_blanks_as": "zero"
	}`
	str3 := str1 + c2 + str2
	// fmt.Println(str3)
	if err := f.AddChart(s.Sheet[1].Name, "F"+strconv.Itoa(cSize+3), str3); err != nil {
		fmt.Println(err)
	}
	// 添加工作表保护
	err = f.ProtectSheet(s.Sheet[1].Name, &excelize.FormatSheetProtection{
		AlgorithmName: "SHA-512",
		Password:      "123456",
		EditScenarios: false,
	})
	if err != nil {
		fmt.Println("ProtectSheet err:", err)

	}

	// 添加备件表
	index = f.NewSheet(s.Sheet[2].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[2].Name, index)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[2].Name, "A1", s.Sheet[2].Title)
	f.SetSheetRow(s.Sheet[2].Name, "A2", &s.Sheet[2].Table.RowTable)
	for i := 0; i < len(s.Sheet[2].Table.ColTable); i++ {
		f.SetCellValue(s.Sheet[2].Name, "A"+strconv.Itoa(3+i), s.Sheet[2].Table.ColTable[i])
	}
	// 设置备件表格式

	rSize = len(s.Sheet[2].Table.RowTable)
	cSize = len(s.Sheet[2].Table.ColTable) + 2
	err = f.MergeCell(s.Sheet[2].Name, "A1", ColToName(rSize)+"1")
	if err != nil {
		fmt.Println("Merge err:", err)
	}
	err = f.SetCellStyle(s.Sheet[2].Name, "A1", ColToName(rSize)+strconv.Itoa(cSize), style1)
	if err != nil {
		fmt.Println("Set style err:", err)
	}
	err = f.SetCellStyle(s.Sheet[2].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	// 设置备件表列宽
	err = f.SetColWidth(s.Sheet[2].Name, "A", "D", 20)
	if err != nil {
		fmt.Println("SetColWidth err:", err)
	}

	// 添加备件往来记录表
	index = f.NewSheet(s.Sheet[3].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[3].Name, index)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[3].Name, "A1", s.Sheet[3].Title)
	f.SetSheetRow(s.Sheet[3].Name, "A2", &s.Sheet[3].Table.RowTable)
	err = f.MergeCell(s.Sheet[3].Name, "A1", ColToName(len(s.Sheet[3].Table.RowTable))+"1")
	if err != nil {
		fmt.Println("Merge err:", err)
	}
	err = f.SetCellStyle(s.Sheet[3].Name, "A1", ColToName(len(s.Sheet[3].Table.RowTable))+"6", style1)
	if err != nil {
		fmt.Println("Set style err:", err)
	}
	err = f.SetCellStyle(s.Sheet[3].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	var colWidth1 = []float64{6.2, 10.5, 11.5, 11.5, 17.3, 38.5, 7, 7, 19, 15}
	for i := 0; i < 10; i++ {
		err = f.SetColWidth(s.Sheet[3].Name, ColToName(1+i), ColToName(1+i), colWidth1[i])
		// fmt.Printf("Width:%T\n", colWidth1[i])
		if err != nil {
			fmt.Println("Set ColWidth err:", err)
		}
	}
	// 添加批注
	for k, v := range s.Sheet[3].Annotation {
		// fmt.Println("k:", k, "v:", v)
		err = f.AddComment(s.Sheet[3].Name, k, v)
		if err != nil {
			fmt.Println("AddComment err:", err)
		}
	}

	// 添加自动筛选
	err = f.AutoFilter(s.Sheet[3].Name, "A2", "J2", "")
	if err != nil {
		fmt.Println("Set AutoFilter err:", err)
	}
	// 添加冻结窗口
	f.SetPanes(s.Sheet[3].Name, `{
			"freeze":true,
			"split":false,
			"x_split":1,
			"y_split":2,
			"top_left_cell":"A2",
			"activate_pane":"topRight",
			"panes":[{
				"sqref":"",
				"active_cell":"",
				"pane":"topRight"
			}]
		}`)

	// 添加批量性工作记录表
	index = f.NewSheet(s.Sheet[4].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[4].Name, index)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[4].Name, "A1", s.Sheet[4].Title)
	f.SetSheetRow(s.Sheet[4].Name, "A2", &s.Sheet[4].Table.RowTable)
	err = f.MergeCell(s.Sheet[4].Name, "A1", ColToName(len(s.Sheet[4].Table.RowTable))+"1")
	if err != nil {
		fmt.Println("Merge err:", err)
	}
	err = f.SetCellStyle(s.Sheet[4].Name, "A1", ColToName(len(s.Sheet[4].Table.RowTable))+"6", style1)
	if err != nil {
		fmt.Println("Set style err:", err)
	}
	err = f.SetCellStyle(s.Sheet[4].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	//设置批量性工作记录表列宽
	var colWidth2 = []float64{11.24, 16.12, 31, 48.9, 9, 13.86, 10.36, 10.36}
	for i := 0; i < 8; i++ {
		err = f.SetColWidth(s.Sheet[4].Name, ColToName(1+i), ColToName(1+i), colWidth2[i])
		if err != nil {
			fmt.Println("Set ColWidth err:", err)
		}
	}

	// 添加自动筛选
	err = f.AutoFilter(s.Sheet[4].Name, "A2", "H2", "")
	if err != nil {
		fmt.Println("Set AutoFilter err:", err)
	}
	// 添加冻结窗口
	f.SetPanes(s.Sheet[4].Name, `{
		"freeze":true,
		"split":false,
		"x_split":1,
		"y_split":2,
		"top_left_cell":"B3",
		"activate_pane":"topRight",
		"panes":[{
			"sqref":"",
			"active_cell":"",
			"pane":"topRight"
		}]
	}`)

	// 现场工作交接记录表
	index = f.NewSheet(s.Sheet[5].Name)
	fmt.Printf("%s index: %d\n", s.Sheet[5].Name, index)
	f.SetActiveSheet(index)
	f.SetCellValue(s.Sheet[5].Name, "A1", s.Sheet[5].Title)
	f.SetSheetRow(s.Sheet[5].Name, "A2", &s.Sheet[5].Table.RowTable)
	err = f.MergeCell(s.Sheet[5].Name, "A1", ColToName(len(s.Sheet[5].Table.RowTable))+"1")
	if err != nil {
		fmt.Println("Merge err:", err)
	}
	err = f.SetCellStyle(s.Sheet[5].Name, "A1", ColToName(len(s.Sheet[5].Table.RowTable))+"6", style1)
	if err != nil {
		fmt.Println("Set style err:", err)
	}
	err = f.SetCellStyle(s.Sheet[5].Name, "A1", "A1", style2)
	if err != nil {
		fmt.Println("SetCellStyle err:", err)
	}
	// 设置交接班记录表列宽
	var colWidth3 = []float64{12, 12, 53.09, 12, 12}
	for i := 0; i < len(colWidth3); i++ {
		err = f.SetColWidth(s.Sheet[5].Name, ColToName(1+i), ColToName(1+i), colWidth3[i])
		if err != nil {
			fmt.Println("SetColWidth err:", err)
		}
	}
	// 添加冻结窗口
	f.SetPanes(s.Sheet[5].Name, `{
		"freeze":true,
		"split":false,
		"x_split":0,
		"y_split":2,
		"top_left_cell":"B3",
		"activate_pane":"topRight",
		"panes":[{
			"sqref":"",
			"active_cell":"",
			"pane":"topRight"
		}]
	}`)

	f.DeleteSheet("Sheet1")

	if err := f.SaveAs(s.FileName); err != nil {
		fmt.Println(err)
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println("Close file err:", err)
		}
	}()
}
